# Copyright (c) 2009 Peter Corbett
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

import colours
import selector
import gamestate

import collections
import re

Tile = collections.namedtuple("Tile", "name ch fg fgd bg bgd passable placemob")
MobType = collections.namedtuple("MobType", "name ch fg bg level rarity generate victory stats auchance au ichances intrinsic spells startitems")
ItemType = collections.namedtuple("ItemType", "name ch fg bg level rarity slots dict")
SpellType = collections.namedtuple("SpellType", "name fg mana target effects")
SpellEffect = collections.namedtuple("SpellEffect", "effect pmult dict")
SlotType = collections.namedtuple("SlotType", "name desc verb mutex")
StatusType = collections.namedtuple("StatusType", "name desc fg dict mutex")

class Data:
    basedict = {"speed": 0, "armour": 0,
                "hthweight": 0, "enc": 0,
                "hthspeed":0, "hthhit": 0, "hthpow": 0, "hthdef": 0,
                "misspeed":0, "mishit": 0, "mispow": 0, "misdef": 0,
                "magspeed": 0, "maghit": 0, "magpow": 0, "magdef": 0,
                "init": 0, "spot": 0, "sneak": 0, "courage": 0}
    
    floortiles = [
        Tile("floor", ".", colours.LIGHTGREY, colours.DARKGREY, colours.BLACK, colours.BLACK, True, True),
        Tile("wall", "#", colours.LIGHTGREY, colours.DARKGREY, colours.BLACK, colours.BLACK, False, False),
        Tile("door", "+", colours.BROWN, colours.BROWN, colours.BLACK, colours.BLACK, True, False),
        Tile("stairs (leading up)", "<", colours.LIGHTGREY, colours.DARKGREY, colours.BLACK, colours.BLACK, True, False),
        Tile("stairs (leading down)", ">", colours.LIGHTGREY, colours.DARKGREY, colours.BLACK, colours.BLACK, True, False)
        ]

    #Stats Str Agi Int WP
    mobtypes = [
        # PC types
        MobType("warrior", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (17, 10, 3, 10), 0, 0, (), {}, (), ["10 potion", "sword", "leather jerkin", "potion"]),
        MobType("pirate", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (15, 15, 5, 5), 0, 0, (), {}, ("Stealth", ), []),
        MobType("thief", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (10, 17, 10, 3), 0, 0, (), {}, ("Stealth", ), ["daggger"]),
        MobType("illusionist", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (5, 15, 15, 5), 0, 0, (), {}, ("Stealth", "Magic Missile"), []),
        MobType("mage", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (3, 10, 17, 10), 0, 0, (), {}, ("Magic Missile", ), ["staff", "violet robes"]),
        MobType("inquisitor", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (5, 5, 15, 15), 0, 0, (), {}, (), []),
        MobType("cleric", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (10, 3, 10, 17), 0, 0, (), {}, (), []),
        MobType("paladin", "@", colours.WHITE, colours.BLACK, 1, 1, False, False, (15, 5, 5, 15), 0, 0, (), {}, (), []),

        # Monster types
        MobType("kobold", "k", colours.YELLOW, colours.BLACK, 1, 1, True, False, (10, 10, 10, 10), 0.5, 10, (0.5, ), {"speed": -5}, ("Cure Light Wounds", "Blink", "Magic Missile"), []),
        MobType("goblin", "o", colours.GREEN, colours.BLACK, 2, 1, True, False, (10, 10, 10, 10), 0.6, 20, (0.75, 0.5), {}, (), []),
        MobType("gnoll", "h", colours.BROWN, colours.BLACK, 3, 1, True, False, (10, 10, 10, 10), 0.4, 25, (1.0, ), {}, (), []),
        MobType("orc", "o", colours.DARKGREEN, colours.BLACK, 4, 1, True, False, (10, 10, 10, 10), 0.6, 30, (), {}, (), []),
        MobType("dark elf", "h", colours.DARKBLUE, colours.BLACK, 5, 1, True, False, (10, 10, 10, 10), 0.8, 30, (), {}, (), []),
        MobType("ogre", "O", colours.BROWN, colours.BLACK, 6, 1, True, False, (10, 10, 10, 10), 0.5, 50, (), {}, (), []),
        MobType("troll", "T", colours.GREEN, colours.BLACK, 7, 1, True, False, (10, 10, 10, 10), 0.25, 100, (), {}, (), []),
        MobType("Lord Midwinter", "B", colours.CYAN, colours.BLACK, 10, 1, False, True, (10, 10, 10, 10), 0.0, 0, (), {}, (), [])
        ]

    itemtypes = [
        ItemType("gold coin", "$", colours.YELLOW, colours.BLACK, 1, 0, None, {}),
        ItemType("dagger", "|", colours.WHITE, colours.BLACK, 1, 1, "weapon", {"hthweight": 5}),
        ItemType("staff", "|", colours.BROWN, colours.BLACK, 2, 1, "weapon", {"hthweight": 5, "hthpow": -2, "hthdef": 1, "maghit": 5, "magpow": 5}),
        ItemType("sword", "|", colours.CYAN, colours.BLACK, 3, 1, "weapon", {"hthweight": 10}),
        ItemType("scroll", "?", colours.WHITE, colours.BLACK, 2, 1, "read", {"effect": "Blink"}),
        ItemType("potion", "!", colours.BLUE, colours.BLACK, 2, 1, "quaff", {"effect": "Cure Light Wounds"}),
        ItemType("wooden shield", "[", colours.BROWN, colours.BLACK, 1, 1, "shield", {"hthdef": 10, "misdef": 10, "enc": 2}),
        ItemType("kite shield", "[", colours.LIGHTGREY, colours.BLACK, 2, 1, "shield", {"hthdef": 20, "misdef": 20, "enc": 4}),
        ItemType("tower shield", "[", colours.LIGHTGREY, colours.BLACK, 4, 1, "shield", {"hthdef": 30, "misdef": 30, "enc": 6}),
        ItemType("leather cap", "[", colours.BROWN, colours.BLACK, 1, 1, "head", {"armour": 2}),
        ItemType("iron helm", "[", colours.LIGHTGREY, colours.BLACK, 3, 1, "head", {"armour": 5, "enc": 1}),
        ItemType("violet robes", "]", colours.MAGENTA, colours.BLACK, 1, 1, "body", {"armour": 2, "enc": 1, "magdef": 10, "magpow": 2}),
        ItemType("leather jerkin", "]", colours.BROWN, colours.BLACK, 1, 1, "body", {"armour": 10, "enc": 2}),
        ItemType("chain shirt", "]", colours.LIGHTGREY, colours.BLACK, 3, 1, "body", {"armour": 20, "enc": 4}),
        ItemType("suit of plate armour", "]", colours.WHITE, colours.BLACK, 5, 1, "body", {"armour": 40, "enc": 8}),
        ItemType("pair of leather boots", "[", colours.BROWN, colours.BLACK, 1, 1, "feet", {"armour": 2}),
        ItemType("pair of steel-capped boots", "[", colours.LIGHTGREY, colours.BLACK, 3, 1, "feet", {"armour": 5, "enc": 1}),
        ItemType("sling", "/", colours.WHITE, colours.BLACK, 1, 0, "sling", {"mispow": 5}),
        ItemType("bow", "/", colours.BROWN, colours.BLACK, 1, 0, "bow", {"mispow": 10}),
        ItemType("sling stone", "\\", colours.DARKGREY, colours.BLACK, 1, 0, "slingstone", {"mispow": 5}),
        ItemType("arrow", "\\", colours.BROWN, colours.BLACK, 1, 0, "arrow", {"mispow": 10}),
        ItemType("throwing knife", "\\", colours.LIGHTGREY, colours.BLACK, 1, 0, "thrown", {"mispow": 10}),
        ]

    spelltypes = [
        SpellType("Cure Light Wounds", colours.WHITE, 10, "self", [SpellEffect("cure", 0.5, {}), SpellEffect("destatus", 1, {"status": "poison"})]),
        SpellType("Bless", colours.WHITE, 10, "self", [SpellEffect("status", 10, {"status": "blessing"})]),
        SpellType("Haste", colours.CYAN, 10, "self", [SpellEffect("status", 10, {"status": "haste"})]),
        SpellType("Poison", colours.GREEN, 10, "bolt", [SpellEffect("status", 20, {"status": "poison"})]),
        SpellType("Fear", colours.CYAN, 10, "bolt", [SpellEffect("status", 20, {"status": "fear"})]),
        SpellType("Blind", colours.CYAN, 10, "bolt", [SpellEffect("status", 20, {"status": "blind"})]),
        SpellType("Confusion", colours.CYAN, 10, "bolt", [SpellEffect("status", 20, {"status": "confused"})]),
        SpellType("Sleep", colours.CYAN, 10, "bolt", [SpellEffect("status", 20, {"status": "sleep"})]),
        SpellType("Blink", colours.MAGENTA, 5, "self", [SpellEffect("blink", 1, {})]),
        SpellType("Teleport Away", colours.MAGENTA, 5, "bolt", [SpellEffect("blink", 1, {})]),
        SpellType("Magic Missile", colours.MAGENTA, 2, "bolt", [SpellEffect("damage", 0.5, {})]),
        SpellType("Protection Aura", colours.WHITE, 5, "self", [SpellEffect("pstatus", 1, {"status": "protectionaura"})]),
        SpellType("Power Aura", colours.WHITE, 5, "self", [SpellEffect("pstatus", 1, {"status": "poweraura"})]),
        SpellType("Stealth", colours.DARKGREY, 0, "self", [SpellEffect("stealth", 1, {})])
        ]

    slottypes = [
        SlotType("weapon", "in right hand", "wield", ()),
        SlotType("bow", "missile weapon", "ready", ("sling", "slingstone", "thrown")),
        SlotType("sling", "missile weapon", "ready", ("bow", "arrow", "thrown")),
        SlotType("slingstone", "ammo", "ready", ("bow", "arrow", "thrown")),
        SlotType("arrow", "ammo", "ready", ("sling", "slingstone", "thrown")),
        SlotType("thrown", "ammo", "ready", ("sling", "bow", "slingstone", "arrow")),
        SlotType("shield", "in left hand", "wear", ()),
        SlotType("head", "on head", "wear", ()),
        SlotType("body", "on body", "wear", ()),
        SlotType("feet", "on feet", "wear", ())
        ]

    statustypes = [
        StatusType("blessing", "Blessed", colours.WHITE, {"armour": 10, "hthpow": 10, "hpregen": 1000}, ()),
        StatusType("haste", "Hastened", colours.WHITE, {"speed": 10, "mpregen": -3000}, ()),
        StatusType("poison", "Poisoned", colours.GREEN, {"hpregen": -2000}, ()),
        StatusType("fear", "Afraid", colours.WHITE, {}, ()),
        StatusType("protectionaura", "Protection Aura", colours.WHITE, {"armour":20}, ("protectionaura", "poweraura")),
        StatusType("poweraura", "Power Aura", colours.WHITE, {"hthpow":10}, ("protectionaura", "poweraura")),
        StatusType("stealth", "Sneaking", colours.DARKGREY, {"speed": -5,}, ()),
        StatusType("blind", "Blind", colours.DARKGREY, {}, ()),
        StatusType("confused", "Confused", colours.WHITE, {}, ()),
        StatusType("sleep", "Asleep", colours.WHITE, {}, ())
        ]
    
    def __init__(self):
        self.floordict = {}
        for i in range(len(self.floortiles)):
            self.floordict[self.floortiles[i].name] = i
        self.mobdict = {}
        for i in range(len(self.mobtypes)):
            self.mobdict[self.mobtypes[i].name] = i
        self.itemdict = {}
        for i in range(len(self.itemtypes)):
            self.itemdict[self.itemtypes[i].name] = i
        self.spelldict = {}
        for i in range(len(self.spelltypes)):
            self.spelldict[self.spelltypes[i].name] = i
        self.slotdict = {}
        for i in range(len(self.slottypes)):
            self.slotdict[self.slottypes[i].name] = i
        self.statusdict = {}
        for i in range(len(self.statustypes)):
            self.statusdict[self.statustypes[i].name] = i

    def generate_items(self, i):
        il = []
        if isinstance(i, list) or isinstance(i, tuple):
            for ii in i:
                il.extend(self.generate_items(ii))
        elif isinstance(i, dict):
            il.extend(self.generate_items(selector.Selector(i).select()))
        elif isinstance(i, str):
            n = 1
            m = re.match("(\\d+) (.+)", i)
            if m:
                n = int(m.group(1))
                i = m.group(2)
            if i in self.itemdict:
                il.append(gamestate.Item(self.itemdict[i], n))
        return il

if __name__=="__main__":
    d = Data()
    l = d.generate_items(("sword", {("bow", "10 arrow"): 50, "10 throwing knife": 50}))
    for i in l:
        print "%s %s" % (i.number, d.itemtypes[i.type].name)
